//
// @Auther: by wujehy 
// @Email:wujehy@qq.com
// @Data:20-3-14
// @Time:下午5:33
//
#include "ListernalControl.h"

// 用户需要传递的数据结构
struct TestUsertData {
    int id;
    std::string name;

};

/**
 * @brief 外部实现 B 监听其的 回调函数
 * @param errCode
 * @param errmsg
 */
void ListernerBcallbacFunc(int errCode, std::string errmsg)
{
    std::cout << " this ListernerBcallbacFunc func , errCode = " << errCode << " errmsg=" << errmsg << std::endl;
}

/**
 * @brief 设置一个 默认的监听器回调
 * @param listernalControl
 */
void setListernerCallback(ListernalControl &listernalControl)
{
    //设置 A 监听器 使用 lambda 表达式方式设置
    listernalControl.setListernerA([](int data)
                                   {
                                       std::cout << " this setListernerCallback func , data = " << data << std::endl;
                                   });

    // 外部函数 的 方式设置监听器 ,传递 函数的指针
    listernalControl.setListernerC(ListernerBcallbacFunc);
}


int main()
{

    std::cout << "----------------ListerA start-------------" << std::endl;

    ListernalControl listernalControlA("listernalA");
    // 设置 AC 监听器 ,当作 内部定义
    setListernerCallback(listernalControlA);

    // 需要用到的时候 设置监听器  用户定义
    listernalControlA.setListernerD([](void *userData)
                                    {
                                        // 函数指针一定要判断 ,防止 内存溢出
                                        if (userData != nullptr)
                                        {

                                            std::cout << "ListernerD userData:" << std::endl;
                                            // 指针转化
                                            TestUsertData *myData = (TestUsertData *) userData;
                                            std::cout << "id:" << myData->id << std::endl;
                                            std::cout << "naem : " << myData->name << std::endl;
                                        } else
                                        {
                                            std::cout << "ListernerD userData is empty" << std::endl;
                                        }

                                    });


    // 触发 事件 A
    listernalControlA.callEvent(Listerner_Type_A);

    // 触发 事件 A B C
    listernalControlA.callEvent(Listerner_Type_A | Listerner_Type_B | Listerner_Type_C);

    // 传递 用户定义数据 触发 事件D
    TestUsertData *userData = new TestUsertData;
    userData->id = 123;
    userData->name = "dada";
    listernalControlA.callEvent(Listerner_Type_D, userData);

    delete userData;
    userData = nullptr;
    // 全部触发, 注意 D 这是后数据被释放了就没有数据了
    listernalControlA.callEvent(Listerner_Type_ALL, userData);

    // 又一个事件发生
    listernalControlA.callEvent(Listerner_Type_B);

    // 传递方式 触发事件A
    listernalControlA.callEventA(12344);
    std::cout << "----------------ListerA end-------------" << std::endl;
    //因为 ListerA 是  栈上内存 所以释放的 最晚

    // 堆上创建的对象 可控 释放
    ListernalControl *listerB = new ListernalControl();

    // 注意 我没有设置 监听器 AC回调
    listerB->setListernerD([](void *userData)
                           {
                               if (userData != nullptr)
                               {

                                   std::cout << "setListernerD AAAAAAAAAAA userData:" << std::endl;
                                   // 指针转化
                                   TestUsertData *myData = (TestUsertData *) userData;
                                   std::cout << "id:" << myData->id << std::endl;
                                   std::cout << "naem : " << myData->name << std::endl;
                               } else
                               {
                                   std::cout << "ListernerD userData is empty" << std::endl;
                               }
                               // 注意 我释放了内存
                               if (userData != nullptr)
                               {
                                   delete userData;
                                   userData = nullptr;
                               }
                           });
    TestUsertData *userData2 = new TestUsertData;
    userData2->id = 123;
    userData2->name = "DDD";
    // 尝试 处罚 A ,它会成功 ,应为 A C 的监听器 储存在 全局变量区 , 设置了 没有取消 就存在 内存不安全
    listerB->callEvent(Listerner_Type_A);
    // B 的 是在 对象内部 随着不同的对象产生 不同的监听器 内存安全
    listerB->callEvent(Listerner_Type_B | Listerner_Type_C);

    std::cout << "callEventD begin id = " << userData2->id << " name = " << userData2->name << std::endl;
    listerB->callEvent(Listerner_Type_D, userData2); // 注意 回调 里面已经 回收了内存 下面是空对象
    // 这里是没数据的
    std::cout << "callEventD after id = " << userData2->id << " name = " << userData2->name << std::endl;
    delete listerB; // 释放 B 这时候 监听其 B 没了 没有设置名称 则是 testListernalControl 的信息

    // 在B 释放后创建 然后比B 慢回收
    ListernalControl listernalControlC("listerner C ");

    // 内存安全 控制

}

